using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PropSys;
using System;
using Unity.Mathematics;

public class PropModule : MonoBehaviour
{
    [Header("Settings")]
    public PropSettings _PS;

    /// <summary>
    /// CurAvlHP-MaxAvlHP-CurMaxHP-MaxHP
    /// </summary>
    private int _maxHP;
    private int _SPPerSlot;
    private int _maxSPSlot;
    private int _MPPerSlot;
    private int _maxMPSlot;
    private int _HPUpgCost;
    private int _SPUpgCost;
    private int _MPUpgCost;
    private int _maxSkillCost;
    public int MaxHP { get => _maxHP; private set => _maxHP = math.max(0, value); }
    public int MaxSPSlot { get => _maxSPSlot; private set => _maxSPSlot = math.max(0, value); }
    public int SPPerSlot { get => _SPPerSlot; private set => _SPPerSlot = math.max(0, value); }
    public int MaxMPSlot { get => _maxMPSlot; private set => _maxMPSlot = math.max(0, value); }
    public int MPPerSlot { get => _MPPerSlot; private set => _MPPerSlot = math.max(0, value); }
    public int HPUpgCost { get => _HPUpgCost; private set => _HPUpgCost = math.max(0, value); }
    public int SPUpgCost { get => _SPUpgCost; private set => _SPUpgCost = math.max(0, value); }
    public int MPUpgCost { get => _MPUpgCost; private set => _MPUpgCost = math.max(0, value); }
    public int MaxSkillCost { get => _maxSkillCost; private set => _maxSkillCost = value; }

    #region HP data
    public int _curMaxHP;
    public int _maxAvlHP;
    public int _curAvlHP;
    public int CurMaxHP { get => _curMaxHP; private set => _curMaxHP = math.max(0, math.min(value, MaxHP)); }
    public int MaxAvlHP { get => _maxAvlHP; private set => _maxAvlHP = math.max(0, math.min(value, CurMaxHP)); }
    public int CurAvlHP { get => _curAvlHP; private set => _curAvlHP = math.max(0, math.min(value, MaxAvlHP)); }
    #endregion
    #region SP data
    public int _curSPSlot;
    public int _curSP;
    public int CurSPSlot { get => _curSPSlot; private set => _curSPSlot = math.max(0, math.min(value, MaxSPSlot)); }
    public int CurSP { get => _curSP; private set => _curSP = math.max(0, math.min(SPPerSlot * _curSPSlot, value)); }
    #endregion
    #region MP data
    public int _curMPSlot;
    public int _curMP;
    public int CurMPSlot { get => _curMPSlot; private set => _curMPSlot = math.max(0, math.min(MaxMPSlot, value)); }
    public int CurMP { get => _curMP; private set => _curMP = math.max(0, math.min(MPPerSlot * _curMPSlot, value)); }
    public int ChargedMPSlot { get => CurMPSlot == 0 ? 0 : CurMP / MPPerSlot; }
    public int RemainingMP { get => CurMP % MPPerSlot; }
    #endregion
    #region Skill data
    public int[] _skillCosts;
    public int[] SkillCosts
    {
        get => _skillCosts;
        private set
        {
            for (int i = 0; i < _skillCosts.Length; i++)
            {
                _skillCosts[i] = math.max(0, math.min(value[i], MaxSkillCost));
            }
        }
    }
    #endregion

    public PropFloat _atk;
    public PropFloat _spd;

    private void Start() { }

    private void Update() { }

    public void IniProp()
    {
        MaxHP = _PS._maxHP;
        MaxSPSlot = _PS._maxSPSlot;
        SPPerSlot = _PS._SPPerSlot;
        MaxMPSlot = _PS._maxMPSlot;
        MPPerSlot = _PS._MPPerSlot;
        HPUpgCost = _PS._HPUpgCost;
        SPUpgCost = _PS._SPUpgCost;
        MPUpgCost = _PS._MPUpgCost;
        MaxSkillCost = _PS._maxSkillCost;
        _atk = new PropFloat(_PS._atk);
        _spd = new PropFloat(_PS._dftSpd);
        RefreshProp();
    }

    public void RefreshProp()
    {
        CurMaxHP = CurMaxHP;
        MaxAvlHP = MaxAvlHP;
        CurAvlHP = CurAvlHP;

        CurSPSlot = CurSPSlot;
        CurSP = CurSP;

        CurMPSlot = CurMPSlot;
        CurMP = CurMP;

        SkillCosts = SkillCosts;
    }

    public void SetBufferData(int curMaxHP, int curSPSlot, int curMPSlot)
    {
        CurMaxHP = curMaxHP;
        CurSPSlot = curSPSlot;
        CurMPSlot = curMPSlot;
        RefreshProp();
    }

    public void UseHP(int HPCnt)
    {
        CurAvlHP -= HPCnt;
        UIMgr.Instance.RfrHUD();
    }

    public void IncHP(int HPCnt)
    {
        MaxAvlHP += HPCnt;
        CurAvlHP = MaxAvlHP;//recover all void HP
        UIMgr.Instance.RfrHUD();
    }

    public void DecHP(int HPCnt)
    {
        MaxAvlHP = CurAvlHP - HPCnt;//dmg all void HP
        RefreshProp();
        UIMgr.Instance.RfrHUD();
        //todo: check state
    }

    public void UseMP(int slotNum)
    {
        if (CurMP < slotNum * MPPerSlot) return;
        CurMP -= slotNum * MPPerSlot;
        UIMgr.Instance.RfrHUD();
    }

    public void RecoverMP(int MPCnt)
    {
        CurMP += MPCnt;
        UIMgr.Instance.RfrHUD();
    }

    public void RegVal(PropType pt, PropReg pr, string key, Func<float> val)
    {
        switch (pt)
        {
            case PropType.ATK:
                _atk.RegVal(pr, key, val);
                break;
            case PropType.SPD:
                _spd.RegVal(pr, key, val);
                break;
            default:
                break;
        }
    }

    public void UregVal(PropType pt, PropReg pr, string key)
    {
        switch (pt)
        {
            case PropType.ATK:
                _atk.UregVal(pr, key);
                break;
            case PropType.SPD:
                _spd.UregVal(pr, key);
                break;
            default:
                break;
        }
    }
}